package com.unresyst;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import org.apache.commons.cli2.OptionException;
import org.apache.mahout.cf.taste.common.NoSuchUserException;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.eval.DataModelBuilder;
import org.apache.mahout.cf.taste.eval.IRStatistics;
import org.apache.mahout.cf.taste.eval.RecommenderBuilder;
import org.apache.mahout.cf.taste.eval.RecommenderEvaluator;
import org.apache.mahout.cf.taste.eval.RecommenderIRStatsEvaluator;
import org.apache.mahout.cf.taste.impl.eval.AverageAbsoluteDifferenceRecommenderEvaluator;
import org.apache.mahout.cf.taste.impl.eval.GenericRecommenderIRStatsEvaluator;
import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.neighborhood.ThresholdUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.CachingRecommender;
import org.apache.mahout.cf.taste.impl.recommender.ClusterSimilarity;
import org.apache.mahout.cf.taste.impl.recommender.FarthestNeighborClusterSimilarity;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.recommender.TreeClusteringRecommender;
import org.apache.mahout.cf.taste.impl.recommender.knn.KnnItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.recommender.knn.NonNegativeQuadraticOptimizer;
import org.apache.mahout.cf.taste.impl.recommender.knn.Optimizer;
import org.apache.mahout.cf.taste.impl.recommender.slopeone.SlopeOneRecommender;
import org.apache.mahout.cf.taste.impl.recommender.svd.ALSWRFactorizer;
import org.apache.mahout.cf.taste.impl.recommender.svd.SVDRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.LogLikelihoodSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.TanimotoCoefficientSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;

public class ItemRecommender {
	public static void main(String... args) throws FileNotFoundException, TasteException, IOException, OptionException {
		DataModel model = new FileDataModel (new File("datasets/datatrain.txt"));
		RecommenderEvaluator evaluator = new AverageAbsoluteDifferenceRecommenderEvaluator ();
		RecommenderBuilder builder7 = new RecommenderBuilder() { 
			@Override 
			public Recommender buildRecommender(DataModel model) throws TasteException {
				UserSimilarity similarity = new PearsonCorrelationSimilarity (model);
				//UserSimilarity similarity = new EuclideanDistanceSimilarity(model);
				//UserSimilarity similarity = new TanimotoCoefficientSimilarity(model);
				//UserNeighborhood neighborhood = new NearestNUserNeighborhood (2, similarity, model); 
				UserNeighborhood neighborhood = new ThresholdUserNeighborhood(0.7, similarity, model);
				return new GenericUserBasedRecommender (model, neighborhood, similarity);
				//ItemSimilarity similarity = new PearsonCorrelationSimilarity(model); 
				//return new GenericItemBasedRecommender(model, similarity);
				//return new SVDRecommender(model, new ALSWRFactorizer(model, 10, 0.05, 10));
				//UserSimilarity similarity = new LogLikelihoodSimilarity(model); 
				//ClusterSimilarity clusterSimilarity = new FarthestNeighborClusterSimilarity(similarity); 
				//return new TreeClusteringRecommender(model, clusterSimilarity, 10);
			}
		};
		Recommender recommender;
		CachingRecommender cachingRecommender;
		File file;
		Long userid;
		Long itemid;
		Integer actualValue;
		double prefScore;
		BufferedReader reader;
		FileWriter writer;
		String s;
		Integer i=0;
		
		recommender=builder7.buildRecommender(model);
		cachingRecommender = new CachingRecommender(recommender);
		
		//System.out.println(cachingRecommender.estimatePreference(282355,1841875));
		file = new File("datasets/datavalidate.txt");
		userid = null;
		itemid = null;
		actualValue = null;
		prefScore = 0;
		reader = new BufferedReader(new FileReader(file));
        writer = new FileWriter("datasets/PearsonThreshold7NeighborhoodUserBasedoutput.txt");		
		s = null;
		do {
			s = reader.readLine();
			if (s == null)
				break;
			s = s.trim();
			String[] parts = s.split(",");
			userid = Long.parseLong(parts[0]);
			itemid = Long.parseLong(parts[1]);
			actualValue = Integer.parseInt(parts[2]);
			String ss;
			try {
			prefScore = cachingRecommender.estimatePreference(userid, itemid);
			}
			catch (NoSuchUserException e) {
				if(actualValue==5) {
					ss = userid + " " + itemid + " 1 0";
				}
				else {
					ss = userid + " " + itemid + " -1 0";
				}
				writer.write(ss);
				writer.append('\n');
				continue;
			}
////			if(prefScore>1.0) {
//				prefScore=1;
//			} else {
//				prefScore=-1;
//			}
			if(actualValue==5) {
				ss = userid + " " + itemid + " 1 "
						+ prefScore;
			}
			else {
				ss = userid + " " + itemid + " -1 "
						+ prefScore;
			}
//			ss = userid + " " + itemid + " " + actualValue + " " + prefScore;
			writer.write(ss);
			writer.append('\n');
//			if(actualValue==5) {
//				System.out.print(":"+ss+":");
//			}
		} while (s != null);
		reader.close();
		writer.close();
		System.out.println("\nOutput threshold 0.7 generated");
		
				
//		double score = evaluator.evaluate( builder, null, model, 0.9, 0.1);
//		System.out.println("Average Absolute Difference:"+score);
//		RecommenderIRStatsEvaluator evaluator2 = new GenericRecommenderIRStatsEvaluator ();
//		IRStatistics stats = evaluator2.evaluate(builder, null, model, null, 4, GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD, 0.1);
//		System.out.println("Precision: "+stats.getPrecision()); 
//		System.out.println("Recall: "+stats.getRecall());
		
//		RecommenderBuilder builder2 = new RecommenderBuilder() { 
//			@Override 
//			public Recommender buildRecommender(DataModel model) throws TasteException {
//				//UserSimilarity similarity = new PearsonCorrelationSimilarity (model);
//				//UserSimilarity similarity = new EuclideanDistanceSimilarity(model);
//				UserSimilarity similarity = new LogLikelihoodSimilarity(model);
//				//UserNeighborhood neighborhood = new NearestNUserNeighborhood (2, similarity, model); 
//				UserNeighborhood neighborhood = new ThresholdUserNeighborhood(0.7, similarity, model);
//				return new GenericUserBasedRecommender (model, neighborhood, similarity);
//			}
//		};
//		score = evaluator.evaluate( builder2, null, model, 0.7, 0.3);
//		System.out.println("Average Absolute Difference:"+score);
	}
}
